package piis;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

import Algorithms.BackPropagation;
import Algorithms.Pruning;
import MainProgram.Plot;
import NeuronNetworkLibrary.Network;
import java.util.Arrays;
import utilities.PiisWriter;
import utilities.Utilities;

public class Test51 {

    static String path = "src/test5";
    public final static int EPOCH = 1000;
    public final static double ERROR = 10e-30;

    public static void main(String[] args) {

        File dir = new File(path);
        String[] files = dir.list();

        if (files == null) {
            System.out.println("Empty directory");
        } else {
            for (int x = 0; x < files.length; x++) {
                if (files[x].endsWith(".in") && files[x].startsWith("2_")) {
                    prepareAndInvoke(files[x]);
                    Network.INIT_WEIGHTS_FLAG = true;
                }
            }
        }
    }

    public static void prepareAndInvoke(String name) {

        try {
            Scanner sc = new Scanner(new File(path + "/" + name));

            //int neuronsInHiddenLayer = sc.nextInt();
            int vDimensions = sc.nextInt();
            double[] minValues = new double[vDimensions];
            double[] maxValues = new double[vDimensions];
            for (int i = 0; i < vDimensions; i++) {
                minValues[i] = Double.valueOf(sc.next());
            }
            for (int j = 0; j < vDimensions; j++) {
                maxValues[j] = Double.valueOf(sc.next());
            }

            ArrayList<Double[]> x = new ArrayList<>(); ///ciekawe :)
            ArrayList<Double> y = new ArrayList<>();
            while (sc.hasNext()) {

                Double[] tempArray = new Double[vDimensions];
                for (int k = 0; k < vDimensions; k++) {
                    tempArray[k] = Double.valueOf(sc.next());
                }
                x.add(tempArray);

                y.add(Double.valueOf(sc.next()));
            }
            sc.close();
            IncrementalPruning(prepareSet(x, vDimensions), prepareOutput(y),
                    name, minValues, maxValues, vDimensions);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static void IncrementalPruning(double[][] trainingSet,
            double[][] desiredOutput, String name,
            double[] minValues, double[] maxValues, int vDimensions) {

        double obtainedResults[][];


        //ArrayList<Double> errors = new ArrayList<>();
        int update = 0;
        double maxAcceptableError = 1e-6;

        Pruning prune = new Pruning(trainingSet,
                desiredOutput, maxAcceptableError);
        prune.startIncremental();

        while (!prune.isDone()) {
            prune.pruneIncremental();
            update++;
            if (update == 1000) {
                System.out.println("Hidden Neurons:" + prune.getHiddenNeuronCounter()
                        + ", Current Error=" + prune.getError());
                update = 0;
            }

            if (prune.getHiddenNeuronCounter() >= 100) {
                System.out.println("FAILURE!");
                break;
            }
        }

        Network network = prune.getNetwork();
        //Save errors
//        PiisWriter.write(
//                Utilities.convertToStringArrayList(errors), 
//                path + "/"+ name.replace(".in", "_train.out")
//                );

        // Second part: calculating values from interval: <-5, 5> 
        double[][] newTrainingSet = Utilities.generateTrainingSet(
                minValues, maxValues, 0.5);
        double[][] newDesiredOutput = new double[newTrainingSet.length][1];

                network.setTrainingSet(newTrainingSet);
        network.setDesiredOutputs(newDesiredOutput);
        network.updateNumberOfPatterns();
        System.out.println("nbr of patterns: " + network.getNumberOfPatterns());
        System.out.println("hidden units: " + 
                Arrays.toString(network.getNeuronsInHiddenLayers()));
        
        
        ArrayList<String> output = new ArrayList<>();
        
        for (int j = 0; j < network.getNumberOfPatterns(); j++) {
            network.calculateNetwork(j);
            String s = Arrays.toString(network.getTrainingSet()[j]);
            s = Utilities.cleanString(s);
            s += " " + network.getOutputLayer().get(0).getCalculatedOutput();
            output.add(s);
        }
        
        PiisWriter.write(output, path + "/" + name.replace(".in", "_result.out"));
        
        System.out.println("Test with file: " + name + " has been finished.");
        
        //TODO: do plot for 1D
        // Show plot 
//        Plot plot = new Plot(
//                name, //window title 
//                name, //plot title
//                trainingSet, //training set 
//                desiredOutput, //desired output
//                network.getTrainingSet(),
//                obtainedResults //obtained result
//                );
//        plot.setVisible(true);

        System.out.println("Test with file: " + name + " has been finished.");
    }

    private static double[][] prepareSet(ArrayList<Double[]> data, int dimensions) {
        double[][] trainingSet = new double[data.size()][dimensions];
        for (int i = 0; i < data.size(); i++) {
            for (int j = 0; j < dimensions; j++) {
                trainingSet[i][j] = data.get(i)[j];
            }
        }
        return trainingSet;
    }

    private static double[][] prepareOutput(ArrayList<Double> data) {
        double[][] output = new double[data.size()][1];
        for (int i = 0; i < output.length; i++) {
            output[i][0] = data.get(i).doubleValue();
        }
        return output;
    }
}
